package com.lsp.proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * AspectProxy是一个面向切面抽象类，类中定义了切入点判断和各种增强，当执行doProxy()方法时，会先进行切入点判断，在执行前置增强等
 * 模板设计模式
 */
public abstract  class AspectProxy implements Proxy{

    private static final Logger logger = LoggerFactory.getLogger(AspectProxy.class);

    @Override
    public Object doProxy(ProxyChain proxyChain) throws Throwable {
        Object result;

        Class<?> targetClass = proxyChain.getTargetClass();
        Method targetMethod = proxyChain.getTargetMethod();
        Object[] methodParams = proxyChain.getMethodParams();

        begin();
        try {
            if(intercept(targetMethod,methodParams)){
                before(targetMethod,methodParams);
                result = proxyChain.deProxyChain();
                after(targetMethod,methodParams);
            } else {
                result = proxyChain.deProxyChain();
            }
        }catch (Exception e){
            logger.error("proxy failure",e);
            error(targetMethod,methodParams);
            throw e;
        }finally {
            end();
        }

        return result;
    }

    /**
     * 开始增强
     */
    public void  begin(){};

    /**
     * 切入点判断
     * @param targetMethod
     * @param methodParams
     * @return
     */
    public boolean intercept(Method targetMethod, Object[] methodParams){return true;}

    /**
     * 前置增强
     * @param targetMethod
     * @param methodParams
     */
    public void  before(Method targetMethod, Object[] methodParams){};

    /**
     * 后置增强
     * @param targetMethod
     * @param methodParams
     */
    public void  after(Method targetMethod, Object[] methodParams){};

    /**
     * 异常增强
     * @param targetMethod
     * @param methodParams
     */
    public void  error(Method targetMethod, Object[] methodParams){};

    /**
     * 最终增强
     */
    public void   end(){};
}
